//http://www.seeedstudio.com/wiki/GROVE_System
//http://www.seeedstudio.com/depot/index.php?main_page=advanced_search_result&search_in_description=1&keyword=grovefamily
//support starter bundle example http://www.seeedstudio.com/wiki/GROVE_-_Starter_Kit_V1.1b

/**
 * Visual Blocks Language
 *
 * Copyright 2012 Fred Lin.
 * https://github.com/gasolin/BlocklyDuino
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Helper functions for generating seeeduino grove blocks.
 * @author gasolin@gmail.com (Fred Lin)
 * @author hi@vox.vg (Zhi-Wei Cai)
 */

goog.provide('Blockly.Arduino.grove');

goog.require('Blockly.Arduino');

Blockly.Arduino.grove_led = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var dropdown_stat = this.getFieldValue('STAT');
  Blockly.Arduino.setups_['setup_green_led_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', OUTPUT);';
  var code = 'digitalWrite(' + dropdown_pin + ',' + dropdown_stat + ');\n'
  return code;
};

Blockly.Arduino.grove_button = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  Blockly.Arduino.setups_['setup_button_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', INPUT);';
  var code = 'digitalRead(' + dropdown_pin + ')';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.grove_touch = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  Blockly.Arduino.setups_['setup_touch_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', INPUT);';
  var code = 'digitalRead(' + dropdown_pin + ')';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.grove_light_sensor = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var code = 'analogRead(' + dropdown_pin + ')';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.grove_rotary_angle = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var code = 'analogRead(' + dropdown_pin + ')';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.grove_tilt_switch = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  Blockly.Arduino.setups_['setup_tilt_switch_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', INPUT);';
  var code = 'digitalRead(' + dropdown_pin + ')';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/*
int buttonPin = 1;
int buzzerPin = 2;

char notes[] = "cdefgabC "; // a space represents a rest
const int length = sizeof(notes); // the number of notes
int beats[length] = { 1,1,1,1,1,1,1,1,1};

int tempo = 300;

void playTone(int tone, int duration) {
  for (long i = 0; i < duration * 1000L; i += tone * 2) {
    digitalWrite(buzzerPin, HIGH);
    delayMicroseconds(tone);
    digitalWrite(buzzerPin, LOW);
    delayMicroseconds(tone);
  }
}

void playNote(char note, int duration) {
  char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'};
  int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };

  // play the tone corresponding to the note name
  for (int i = 0; i < length; i++) {
    if (names[i] == note) {
      playTone(tones[i], duration);
    }
  }
}

void setup() {
  pinMode(buzzerPin, OUTPUT);
  pinMode(buttonPin,INPUT);
}

void loop() {
  if(digitalRead(buttonPin))
  {
  for (int i = 0; i < length; i++) {
    if (notes[i] == ' ') {
      delay(beats[i] * tempo); // rest
    } else {
      playNote(notes[i], beats[i] * tempo);
    }

    // pause between notes
    delay(tempo / 20);
  }
  }
}
*/
Blockly.Arduino.grove_buzzer = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var dropdown_stat = this.getFieldValue('STAT');
  Blockly.Arduino.setups_['setup_piezo_buzzer_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', OUTPUT);';
  var code = 'digitalWrite(' + dropdown_pin + ',' + dropdown_stat + ');\n'
  return code;
};

Blockly.Arduino.grove_relay = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var dropdown_stat = this.getFieldValue('STAT');
  Blockly.Arduino.setups_['setup_relay_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', OUTPUT);';
  var code = 'digitalWrite(' + dropdown_pin + ', ' + dropdown_stat + ');\n'
  return code;
};

Blockly.Arduino.grove_temporature_sensor = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var code = 'round('+'1/(log(((float)(1023-analogRead(' + dropdown_pin + '))*10000/analogRead(' + dropdown_pin + '))/10000)/3975+1/298.15)-273.15'+')';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/*
#include <SerialLCD.h>
#include <SoftwareSerial.h> //this is a must
SerialLCD slcd(11,12);//this is a must, assign soft serial pins

void setup()
{
  slcd.begin();// set up :
}

void loop()
{
  slcd.backlight();// Turn on the backlight: //noBacklight
  slcd.setCursor(0,0); // set the cursor to (0,0):
  slcd.print("  Seeed Studio"); // Print a message to the LCD.
  slcd.setCursor(0,1); //line 2
  slcd.print("   Starter kit   ");
  delay(5000);
  //slcd.scrollDisplayLeft();//scrollDisplayRight/autoscroll/
  //slcd.clear();
  //Power/noPower
}
*/

var _get_next_pin = function(dropdown_pin) {
  var NextPIN = dropdown_pin;
  if(parseInt(NextPIN)){
    NextPIN = parseInt(dropdown_pin)+1;
  } else {
    NextPIN = 'A'+(parseInt(NextPIN.slice(1,NextPIN.length))+1);
  }
  //check if NextPIN in bound
  var pinlen = profile.default.digital.length;
  var notExist=true;
  for(var i=0;i<pinlen;i++){
    if(profile.default.digital[i][1] == NextPIN){
      notExist=false;
    }
  }
  if(notExist){
    alert("Grove Sensor needs PIN#+1 port, current setting is out of bound.");
    return null;
  } else {
    return NextPIN;
  }
}

Blockly.Arduino.grove_serial_lcd_print = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var text = Blockly.Arduino.valueToCode(this, 'TEXT',
                                         Blockly.Arduino.ORDER_UNARY_POSTFIX) || '\'\'';
  var text2 = Blockly.Arduino.valueToCode(this, 'TEXT2',
                                          Blockly.Arduino.ORDER_UNARY_POSTFIX) || '\'\'';
  var delay_time = Blockly.Arduino.valueToCode(this, 'DELAY_TIME', Blockly.Arduino.ORDER_ATOMIC) || '1000';
  /*if(text.length>16||text2.length>16){
      alert("string is too long");
  }*/
  Blockly.Arduino.definitions_['define_seriallcd'] = '#include <SerialLCD.h>\n';
  Blockly.Arduino.definitions_['define_softwareserial'] = '#include <SoftwareSerial.h>\n';
  //generate PIN#+1 port
  var NextPIN = _get_next_pin(dropdown_pin);

  Blockly.Arduino.definitions_['var_lcd_' + dropdown_pin] = 'SerialLCD slcd_' + dropdown_pin + '(' + dropdown_pin + ','+NextPIN+');\n';

  Blockly.Arduino.setups_['setup_lcd_' + dropdown_pin] = 'slcd_' + dropdown_pin + '.begin();\n';
  var code = 'slcd_' + dropdown_pin + '.backlight();\n';
  code    += 'slcd_' + dropdown_pin + '.setCursor(0,0);\n';
  code    += 'slcd_' + dropdown_pin + '.print('+text+');\n';//text.replace(new RegExp('\'',"gm"),'')
  code    += 'slcd_' + dropdown_pin + '.setCursor(0,1);\n';
  code    += 'slcd_' + dropdown_pin + '.print('+text2+');\n';
  code    += 'delay('+delay_time+');\n';
  return code;
};

Blockly.Arduino.grove_serial_lcd_power = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var dropdown_stat = this.getFieldValue('STAT');

  Blockly.Arduino.definitions_['define_seriallcd'] = '#include <SerialLCD.h>\n';
  Blockly.Arduino.definitions_['define_softwareserial'] = '#include <SoftwareSerial.h>\n';
  //generate PIN#+1 port
  var NextPIN = _get_next_pin(dropdown_pin);

  Blockly.Arduino.definitions_['var_lcd' + dropdown_pin] = 'SerialLCD slcd_' + dropdown_pin + '(' + dropdown_pin + ','+NextPIN+');\n';
  var code = 'slcd_' + dropdown_pin;
  if(dropdown_stat==="ON"){
    code += '.Power();\n';
  } else {
    code += '.noPower();\n';
  }
  return code;
};

Blockly.Arduino.grove_serial_lcd_effect = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var dropdown_stat = this.getFieldValue('STAT');

  Blockly.Arduino.definitions_['define_seriallcd'] = '#include <SerialLCD.h>\n';
  Blockly.Arduino.definitions_['define_softwareserial'] = '#include <SoftwareSerial.h>\n';
  //generate PIN#+1 port
  var NextPIN = _get_next_pin(dropdown_pin);

  Blockly.Arduino.definitions_['var_lcd' + dropdown_pin] = 'SerialLCD slcd_' + dropdown_pin + '(' + dropdown_pin + ','+NextPIN+');\n';
  var code = 'slcd_' + dropdown_pin;
  if(dropdown_stat==="LEFT"){
    code += '.scrollDisplayLeft();\n';
  } else if(dropdown_stat==="RIGHT"){
    code += '.scrollDisplayRight();\n';
  } else {
    code += '.autoscroll();\n';
  }
  return code;
};

Blockly.Arduino.grove_sound_sensor = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var code = 'analogRead(' + dropdown_pin + ')';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.grove_pir_motion_sensor = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  Blockly.Arduino.setups_['setup_input_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', INPUT);';
  var code = 'digitalRead(' + dropdown_pin + ')';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.grove_line_finder = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  Blockly.Arduino.setups_['setup_input_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', INPUT);';
  var code = 'digitalRead(' + dropdown_pin + ')';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.grove_ultrasonic_ranger = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var dropdown_unit = this.getFieldValue('UNIT');
  Blockly.Arduino.definitions_['define_ultrasonic'] = '#include "Ultrasonic.h"\n';
  Blockly.Arduino.definitions_['var_ultrasonic' + dropdown_pin] = 'Ultrasonic __ultrasonic' + dropdown_pin + '(' + dropdown_pin + ');\n';
  var code;
  if (dropdown_unit === "cm") {
    code = '__ultrasonic' + dropdown_pin + '.MeasureInCentimeters()';
  } else {
    code = '__ultrasonic' + dropdown_pin + '.MeasureInInches()';
  }
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.grove_motor_shield = function() {
  var dropdown_direction = this.getFieldValue('DIRECTION');
  var speed = 127;//Blockly.Arduino.valueToCode(this, 'SPEED', Blockly.Arduino.ORDER_ATOMIC) || '127';
  Blockly.Arduino.setups_["setup_motor"] = "pinMode(8,OUTPUT);//I1\n"+
    "  pinMode(11,OUTPUT);//I2\n"+
    "  pinMode(9,OUTPUT);//speedPinA\n"+
    "  pinMode(12,OUTPUT);//I3\n"+
    "  pinMode(13,OUTPUT);//i4\n"+
    "  pinMode(10,OUTPUT);//speedPinB\n";
  var code = "";
  if(dropdown_direction==="forward"){
    Blockly.Arduino.definitions_['define_forward'] = "void forward()\n"+
      "{\n"+
      "  analogWrite(9,"+speed+");//input a simulation value to set the speed\n"+
      "  analogWrite(10,"+speed+");\n"+
      "  digitalWrite(13,HIGH);//turn DC Motor B move clockwise\n"+
      "  digitalWrite(12,LOW);\n"+
      "  digitalWrite(11,LOW);//turn DC Motor A move anticlockwise\n"+
      "  digitalWrite(8,HIGH);\n"+
      "}\n";
    code="forward();\n";
  } else if (dropdown_direction==="right") {
    Blockly.Arduino.definitions_['define_right'] = "void right()\n"+
      "{\n"+
      "  analogWrite(9,"+speed+");//input a simulation value to set the speed\n"+
      "  analogWrite(10,"+speed+");\n"+
      "  digitalWrite(13,LOW);//turn DC Motor B move anticlockwise\n"+
      "  digitalWrite(12,HIGH);\n"+
      "  digitalWrite(11,LOW);//turn DC Motor A move anticlockwise\n"+
      "  digitalWrite(8,HIGH);\n"+
      "}\n\n";
    code="right();\n";
  } else if (dropdown_direction==="left") {
    Blockly.Arduino.definitions_['define_left'] = "void left()\n"+
      "{\n"+
      "  analogWrite(9,"+speed+");//input a simulation value to set the speed\n"+
      "  analogWrite(10,"+speed+");\n"+
      "  digitalWrite(13,HIGH);//turn DC Motor B move clockwise\n"+
      "  digitalWrite(12,LOW);\n"+
      "  digitalWrite(11,HIGH);//turn DC Motor A move clockwise\n"+
      "  digitalWrite(8,LOW);\n"+
      "}\n\n";
    code="left();\n";
  } else if (dropdown_direction==="backward"){
    Blockly.Arduino.definitions_['define_backward'] = "void backward()\n"+
      "{\n"+
      "  analogWrite(9,"+speed+");//input a simulation value to set the speed\n"+
      "  analogWrite(10,"+speed+");\n"+
      "  digitalWrite(13,LOW);//turn DC Motor B move anticlockwise\n"+
      "  digitalWrite(12,HIGH);\n"+
      "  digitalWrite(11,HIGH);//turn DC Motor A move clockwise\n"+
      "  digitalWrite(8,LOW);\n"+
      "}\n\n";
    code="backward();\n";
  } else if (dropdown_direction==="stop"){
    Blockly.Arduino.definitions_['define_stop'] = "void stop()\n"+
      "{\n"+
      "digitalWrite(9,LOW);// Unenble the pin, to stop the motor. this should be done to avid damaging the motor.\n"+
      "digitalWrite(10,LOW);\n"+
      "delay(1000);\n"+
      "}\n\n"
    code="stop();\n";
  }
  return code;
};

Blockly.Arduino.grove_thumb_joystick =  function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var dropdown_axis = this.getFieldValue('AXIS');
  var stickPIN = "0"
  if(dropdown_axis==="y"){
    stickPIN = _get_next_pin(dropdown_pin);
  } else {
    stickPIN = dropdown_pin
  }
  var code = 'analogRead('+stickPIN+')';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

function hexToR(h) {return parseInt((cutHex(h)).substring(0,2),16)}
function hexToG(h) {return parseInt((cutHex(h)).substring(2,4),16)}
function hexToB(h) {return parseInt((cutHex(h)).substring(4,6),16)}
function cutHex(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h}

Blockly.Arduino.grove_rgb_led = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var NextPIN = _get_next_pin(dropdown_pin);

  Blockly.Arduino.setups_['setup_input_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', OUTPUT);';
  Blockly.Arduino.setups_['setup_input_'+NextPIN] = 'pinMode('+NextPIN+', OUTPUT);';
  Blockly.Arduino.definitions_['define_uint8'] = "#define uint8 unsigned char";
  Blockly.Arduino.definitions_['define_uint16'] = "#define uint16 unsigned int";
  Blockly.Arduino.definitions_['define_uint32'] = "#define uint32 unsigned long int";
  Blockly.Arduino.definitions_['define_clkproduce_' + dropdown_pin] = "void ClkProduce_"+dropdown_pin+"(void)\n"+
    "{\n"+
    "  digitalWrite("+dropdown_pin+", LOW);\n"+
    "  delayMicroseconds(20);\n"+
    "  digitalWrite("+dropdown_pin+", HIGH);\n"+
    "  delayMicroseconds(20);\n"+
    "}\n";
  Blockly.Arduino.definitions_['define_send32zero_' + dropdown_pin] = "void Send32Zero_"+dropdown_pin+"(void)\n"+
    "{\n"+
    "  uint8 i;\n"+
    "  for (i=0; i<32; i++)\n"+
    "  {\n"+
    "    digitalWrite("+NextPIN+", LOW);\n"+
    "    ClkProduce_"+dropdown_pin+"();\n"+
    "  }\n"+
    "}\n";
  Blockly.Arduino.definitions_['define_taskanticode'] = "uint8 TakeAntiCode(uint8 dat)\n"+
    "{\n"+
    "  uint8 tmp = 0;\n"+
    "  if ((dat & 0x80) == 0)\n"+
    "  {\n"+
    "    tmp |= 0x02;\n"+
    "  }\n"+
    "  \n"+
    "  if ((dat & 0x40) == 0)\n"+
    "  {\n"+
    "    tmp |= 0x01;\n"+
    "  }\n"+
    "  return tmp;\n"+
    "}\n";
  Blockly.Arduino.definitions_['define_datasend_' + dropdown_pin] = "// gray data\n"+
    "void DatSend_"+dropdown_pin+"(uint32 dx)\n"+
    "{\n"+
    "  uint8 i;\n"+
    "  for (i=0; i<32; i++)\n"+
    "  {\n"+
    "    if ((dx & 0x80000000) != 0)\n"+
    "    {\n"+
    "      digitalWrite("+NextPIN+", HIGH);\n"+
    "    }\n"+
    "    else\n"+
    "    {\n"+
    "      digitalWrite("+NextPIN+", LOW);\n"+
    "    }\n"+
    "  dx <<= 1;\n"+
    "  ClkProduce_"+dropdown_pin+"();\n"+
    "  }\n"+
    "}\n";
  Blockly.Arduino.definitions_['define_datadealwithsend_' + dropdown_pin] = "// data processing\n"+
    "void DataDealWithAndSend_"+dropdown_pin+"(uint8 r, uint8 g, uint8 b)\n"+
    "{\n"+
    "  uint32 dx = 0;\n"+
    "  dx |= (uint32)0x03 << 30;             // highest two bits 1，flag bits\n"+
    "  dx |= (uint32)TakeAntiCode(b) << 28;\n"+
    "  dx |= (uint32)TakeAntiCode(g) << 26;\n"+
    "  dx |= (uint32)TakeAntiCode(r) << 24;\n"+
    "\n"+
    "  dx |= (uint32)b << 16;\n"+
    "  dx |= (uint32)g << 8;\n"+
    "  dx |= r;\n"+
    "\n"+
    "  DatSend_"+dropdown_pin+"(dx);\n"+
    "}\n";
  var code = "Send32Zero_"+dropdown_pin+"(); // begin\n";
  //console.log(this.itemCount_);
  if (this.itemCount_ == 0) {
    return '';
  } else {
    for (var n = 0; n < this.itemCount_; n++) {
      var colour_rgb = this.getFieldValue('RGB'+n);
      //console.log(colour_rgb);
      code += "DataDealWithAndSend_"+dropdown_pin+"("+hexToR(colour_rgb)+", "+hexToG(colour_rgb)+", "+hexToB(colour_rgb)+"); // first node data\n";
    }
  }
  code += "Send32Zero_"+dropdown_pin+"();  // send to update data\n";
  return code;
};

Blockly.Arduino.grove_bluetooth_slave = function() {
  var dropdown_pin = this.getFieldValue('PIN');
  var NextPIN = _get_next_pin(dropdown_pin);
  var name = this.getFieldValue('NAME')
  var pincode = this.getFieldValue('PINCODE');
  var statement_receive = Blockly.Arduino.statementToCode(this, "RCV")
  var statement_send = Blockly.Arduino.statementToCode(this, "SNT")
  /* if(pincode.length != 4){
    alert("pincode length should be 4");
  } */
  Blockly.Arduino.definitions_['define_softwareserial'] = '#include <SoftwareSerial.h>\n';
  Blockly.Arduino.definitions_['var_bluetooth_' + dropdown_pin] = 'SoftwareSerial blueToothSerial_' + dropdown_pin + '(' + dropdown_pin + ','+NextPIN+');\n';

  Blockly.Arduino.setups_['setup_bluetooth_' + dropdown_pin] = 'Serial.begin(9600);\n';
  Blockly.Arduino.setups_['setup_bluetooth_' + dropdown_pin] += '  pinMode(' + dropdown_pin + ', INPUT);\n';
  Blockly.Arduino.setups_['setup_bluetooth_' + dropdown_pin] += '  pinMode('+NextPIN+', OUTPUT);\n';
  Blockly.Arduino.setups_['setup_bluetooth_' + dropdown_pin] += '  setupBlueToothConnection_' + dropdown_pin + '();\n';

  Blockly.Arduino.definitions_['define_setupBlueToothConnection_' + dropdown_pin] = 'void setupBlueToothConnection_' + dropdown_pin + '()\n'+
    '{\n'+
    '  blueToothSerial_' + dropdown_pin + '.begin(38400); //Set BluetoothBee BaudRate to default baud rate 38400\n'+
    '  blueToothSerial_' + dropdown_pin + '.print("\\r\\n+STWMOD=0\\r\\n"); //set the bluetooth work in slave mode\n'+
    '  blueToothSerial_' + dropdown_pin + '.print("\\r\\n+STNA='+name+'\\r\\n"); //set the bluetooth name as "'+name+'"\n'+
    '  blueToothSerial_' + dropdown_pin + '.print("\\r\\n+STPIN=0000\\r\\n");//Set SLAVE pincode"0000"\n'+
    '  blueToothSerial_' + dropdown_pin + '.print("\\r\\n+STOAUT=1\\r\\n"); // Permit Paired device to connect me\n'+
    '  blueToothSerial_' + dropdown_pin + '.print("\\r\\n+STAUTO=0\\r\\n"); // Auto-connection should be forbidden here\n'+
    '  delay(2000); // This delay is required.\n'+
    '  blueToothSerial_' + dropdown_pin + '.print("\\r\\n+INQ=1\\r\\n"); //make the slave bluetooth inquirable \n'+
    '  Serial.println("The slave bluetooth is inquirable!");\n'+
    '  delay(2000); // This delay is required.\n'+
    '  blueToothSerial_' + dropdown_pin + '.flush();\n'+
    '}\n';
  var code = 'char recvChar_' + dropdown_pin + ';\n'+
      'while(1) {\n'+
      '  if(blueToothSerial_' + dropdown_pin + '.available()) {//check if there is any data sent from the remote bluetooth shield\n'+
      '    recvChar_' + dropdown_pin + ' = blueToothSerial_' + dropdown_pin + '.read();\n'+
      '    Serial.print(recvChar_' + dropdown_pin + ');\n'+
      statement_receive+
      '  }\n'+
      '  if(Serial.available()){//check if there is any data sent from the local serial terminal, you can add the other applications here\n'+
      '    recvChar_' + dropdown_pin + ' = Serial.read();\n'+
      '    blueToothSerial_' + dropdown_pin + '.print(recvChar_' + dropdown_pin + ');\n'+
      statement_send+
      '  }\n'+
      '}\n';
  return code;
};

Blockly.Arduino.grove_rgb_lcd_setcolor = function() {
  Blockly.Arduino.definitions_['define_wire'] = '#include <Wire.h>\n';
  Blockly.Arduino.definitions_['define_rgb_lcd'] = '#include "rgb_lcd.h"\n' + 'rgb_lcd grove_lcd;\n';
  var colour_rgb = this.getFieldValue('RGB');
  var code = "grove_lcd.setRGB("+hexToR(colour_rgb)+", "+hexToG(colour_rgb)+", "+hexToB(colour_rgb)+");\n";
  return code;
};

Blockly.Arduino.grove_rgb_lcd_begin = function() {
  var cols = this.getFieldValue('COLS');
  var rows = this.getFieldValue('ROWS');
  Blockly.Arduino.definitions_['define_wire'] = '#include <Wire.h>\n';
  Blockly.Arduino.definitions_['define_rgb_lcd'] = '#include "rgb_lcd.h"\n' + 'rgb_lcd grove_lcd;\n';
  var code = 'grove_lcd.begin(' + cols + ',' + rows + ');\n';
  return code;
}

Blockly.Arduino.grove_rgb_lcd_print = function() {
  var text = Blockly.Arduino.valueToCode(this, 'PRINT', Blockly.Arduino.ORDER_NONE)
  Blockly.Arduino.definitions_['define_wire'] = '#include <Wire.h>\n';
  Blockly.Arduino.definitions_['define_rgb_lcd'] = '#include "rgb_lcd.h"\n' + 'rgb_lcd grove_lcd;\n';
  var code = 'grove_lcd.print(' + text + ');\n';
  return code;
}

Blockly.Arduino.grove_rgb_lcd_setcursor = function() {
  var col = this.getFieldValue('COL');
  var row = this.getFieldValue('ROW');
  Blockly.Arduino.definitions_['define_wire'] = '#include <Wire.h>\n';
  Blockly.Arduino.definitions_['define_rgb_lcd'] = '#include "rgb_lcd.h"\n' + 'rgb_lcd grove_lcd;\n';
  var code = 'grove_lcd.setCursor(' + col + ',' + row + ');\n';
  return code;
}

Blockly.Arduino.grove_rgb_lcd_custom_setcursor = function() {
  var col = Blockly.Arduino.valueToCode(this, 'COL', Blockly.Arduino.ORDER_NONE) || "0"
  var row = Blockly.Arduino.valueToCode(this, 'ROW', Blockly.Arduino.ORDER_NONE) || "0"

  Blockly.Arduino.definitions_['define_wire'] = '#include <Wire.h>\n';
  Blockly.Arduino.definitions_['define_rgb_lcd'] = '#include "rgb_lcd.h"\n' + 'rgb_lcd grove_lcd;\n';
  var code = 'grove_lcd.setCursor(' + col + ',' + row + ');\n';
  return code;
}


Blockly.Arduino.grove_rgb_lcd_clear = function() {
  Blockly.Arduino.definitions_['define_wire'] = '#include <Wire.h>\n';
  Blockly.Arduino.definitions_['define_rgb_lcd'] = '#include "rgb_lcd.h"\n' + 'rgb_lcd grove_lcd;\n';
  var code = 'grove_lcd.clear();\n';
  return code;
}

Blockly.Arduino.grove_rgb_lcd_scrolldisplayleft = function() {
  Blockly.Arduino.definitions_['define_wire'] = '#include <Wire.h>\n';
  Blockly.Arduino.definitions_['define_rgb_lcd'] = '#include "rgb_lcd.h"\n' + 'rgb_lcd grove_lcd;\n';
  var code = 'grove_lcd.scrollDisplayLeft();\n';
  return code;
}

Blockly.Arduino.grove_rgb_lcd_scrolldisplayright = function() {
  Blockly.Arduino.definitions_['define_wire'] = '#include <Wire.h>\n';
  Blockly.Arduino.definitions_['define_rgb_lcd'] = '#include "rgb_lcd.h"\n' + 'rgb_lcd grove_lcd;\n';
  var code = 'grove_lcd.scrollDisplayRight();\n';
  return code;
}

Blockly.Arduino.grove_rgb_lcd_switch_scroll = function(){
  var sw = this.getFieldValue('SW');
  var code = 'grove_lcd.';
  if( sw == 1) code += 'autoscroll();\n';
  else         code += 'noAutoscroll();\n';
  return code;
}

Blockly.Arduino.grove_rgb_lcd_autoscroll = function() {
  var code = 'grove_lcd.autoscroll();\n';
  return code;
}

Blockly.Arduino.grove_rgb_lcd_noautoscroll = function() {
  var code = 'grove_lcd.noAutoscroll();\n';
  return code;
}

Blockly.Arduino.grove_rgb_lcd_lefttoright = function() {
  var code = 'grove_lcd.leftToRight();\n';
  return code;
}

Blockly.Arduino.grove_rgb_lcd_righttoleft = function() {
  var code = 'grove_lcd.rightToLeft();\n';
  return code;
}

Blockly.Arduino.grove_ir_receiver_init = function(){
  var pin = this.getFieldValue('PIN');

  Blockly.Arduino.definitions_['define_irsendrev'] = '#include <IRSendRev.h>\n';
  Blockly.Arduino.setups_['setup_ir_init_' + pin] = 'IR.Init(' + pin + ');\n';

  var code = "";
  return code;
}

Blockly.Arduino.grove_ir_receiver_check_data = function(){

  var code = "IR.IsDta()";
  return [code, Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.grove_ir_receiver_receive = function(){
  Blockly.Arduino.definitions_['define_receive_datalength'] = 'unsigned char dta[20];\n';

  var code = 'IR.Recv(dta);\n';
  return code;
}

Blockly.Arduino.grove_ir_receiver_data = function(){
  Blockly.Arduino.definitions_['define_irsendrev'] = '#include <IRSendRev.h>\n';

  var code = 'dta[6]';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.grove_ir_emitter_send = function(){
  var data = Blockly.Arduino.valueToCode(this, 'DATA', Blockly.Arduino.ORDER_NONE) || 0
  if (data < 0){
    data = 0;
  }else if(data > 255){
    data = 255;
  }
  var length = 1;

  Blockly.Arduino.definitions_['define_irsendrev'] = '#include <IRSendRev.h>\n';
  Blockly.Arduino.definitions_['define_emmiter_datalength'] = 'unsigned char dtaSend[20];\n';
  Blockly.Arduino.definitions_['define_dtainit'] = 'void dtaInit()\n'
    + '{\n'
    + '  dtaSend[0] = 11;\n'
    + '  dtaSend[1] = 180;\n'
    + '  dtaSend[2] = 91;\n'
    + '  dtaSend[3] = 11;\n'
    + '  dtaSend[4] = 33;\n'
    + '  dtaSend[5] = ' + length +';\n'
    + '}\n';

  var code = 'dtaInit();\n';
  code += 'dtaSend[' + 6 + '] = ' + data + ';\n';
  code += 'IR.Send(dtaSend,38);\n';
  return code;
}

Blockly.Arduino.grove_temporature_humidity_sensor = function() {

  var dropdown_pin = this.getFieldValue('PIN');
  var dropdown_unit = this.getFieldValue('UNIT');

  Blockly.Arduino.definitions_['include_temporature_humidity'] = '#include "DHT.h"\n';
  Blockly.Arduino.definitions_['define_temporature_humidity' + dropdown_pin] = 'DHT __dht' + dropdown_pin + '(' + dropdown_pin + ', DHT22);\n';

  Blockly.Arduino.setups_['setup_temporature_humidity' + dropdown_pin] = '__dht' + dropdown_pin + '.begin();\n';

  var code;
  if (dropdown_unit === "h") {
    code = '__dht' + dropdown_pin + '.readHumidity()';
  } else if (dropdown_unit === "c") {
    code = '__dht' + dropdown_pin + '.readTemperature()';
  } else {
    code = '__dht' + dropdown_pin + '.convertCtoF(__dht' + dropdown_pin + '.readTemperature())';
  }
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.grove_led_bar = function() {

  var dropdown_pin = this.getFieldValue('PIN');
  var NextPIN = _get_next_pin(dropdown_pin);
  var level = Blockly.Arduino.valueToCode(this, 'LEVEL', Blockly.Arduino.ORDER_ATOMIC) || 0;
  var prefix = '';
  // if (isNaN(level)) {
  //     level = 0;
  // } else {
  //     level = Math.min(10, Math.max(0, level));
  // }

  Blockly.Arduino.definitions_['include_grove_led_bar'] = '#include <Grove_LED_Bar.h>\n';
  Blockly.Arduino.definitions_['define_grove_led_bar' + dropdown_pin] = 'Grove_LED_Bar __bar' + dropdown_pin + '(' + NextPIN + ', ' +  dropdown_pin + ', 0);\n';

  Blockly.Arduino.setups_['setup_grove_led_bar' + dropdown_pin] = '__bar' + dropdown_pin + '.begin();\n';

  var code = '__bar' + dropdown_pin + '.setLevel(' + level + ');\n';
  return code;
};

Blockly.Arduino.grove_oled_display_clear = function() {
  Blockly.Arduino.definitions_['include_wire_lib'] = '#include <Wire.h>\n';
  Blockly.Arduino.definitions_['include_seeedoled_lib'] = '#include <SeeedOLED.h>\n';

  Blockly.Arduino.setups_['setup_wire_lib'] = 'Wire.begin();\n';
  Blockly.Arduino.setups_['setup_seeedoled_lib_init'] = 'SeeedOled.init();\n';
  Blockly.Arduino.setups_['setup_seeedoled_lib_deactivatescroll'] = 'SeeedOled.deactivateScroll();\n';
  Blockly.Arduino.setups_['setup_seeedoled_lib_setmode'] = 'SeeedOled.setPageMode();\n';

  var code = 'SeeedOled.clearDisplay();\n';
  return code;
};

Blockly.Arduino.grove_oled_display_set_cursor = function() {
  var row = Blockly.Arduino.valueToCode(this, 'ROW', Blockly.Arduino.ORDER_ATOMIC) || 0;
  var col = Blockly.Arduino.valueToCode(this, 'COL', Blockly.Arduino.ORDER_ATOMIC) || 0;

  // if (isNaN(x)) {
  //     x = 0;
  // }
  // if (isNaN(y)) {
  //     y = 0;
  // }

  Blockly.Arduino.definitions_['include_wire_lib'] = '#include <Wire.h>\n';
  Blockly.Arduino.definitions_['include_seeedoled_lib'] = '#include <SeeedOLED.h>\n';

  Blockly.Arduino.setups_['setup_wire_lib'] = 'Wire.begin();\n';
  Blockly.Arduino.setups_['setup_seeedoled_lib_init'] = 'SeeedOled.init();\n';
  Blockly.Arduino.setups_['setup_seeedoled_lib_deactivatescroll'] = 'SeeedOled.deactivateScroll();\n';
  Blockly.Arduino.setups_['setup_seeedoled_lib_setmode'] = 'SeeedOled.setPageMode();\n';

  var code = 'SeeedOled.setTextXY(' + row + ', ' + col + ');\n';
  return code;
};

Blockly.Arduino.grove_oled_display_put = function() {

  var type = this.getFieldValue('TYPE');
  var value;
  if (type === "Number" ||
      type === "Float") {
      value = Blockly.Arduino.valueToCode(this, 'VALUE', Blockly.Arduino.ORDER_ATOMIC) || 0;
    //   if (isNaN(value)) {
    //       value = 0;
    //   }
    //   if (type === "Number") {
    //       value = parseInt(value);
    //       value = Math.round(value);
    //   } else {
    //       value = parseFloat(value);
    //   }
    //   value = value.toString();
  } else {
      value = Blockly.Arduino.valueToCode(this, 'VALUE', Blockly.Arduino.ORDER_ATOMIC) || '';
  }

  Blockly.Arduino.definitions_['include_wire_lib'] = '#include <Wire.h>\n';
  Blockly.Arduino.definitions_['include_seeedoled_lib'] = '#include <SeeedOLED.h>\n';

  Blockly.Arduino.setups_['setup_wire_lib'] = 'Wire.begin();\n';
  Blockly.Arduino.setups_['setup_seeedoled_lib_init'] = 'SeeedOled.init();\n';
  Blockly.Arduino.setups_['setup_seeedoled_lib_deactivatescroll'] = 'SeeedOled.deactivateScroll();\n';
  Blockly.Arduino.setups_['setup_seeedoled_lib_setmode'] = 'SeeedOled.setPageMode();\n';

  var code = 'SeeedOled.put' + type + '(' + value + ');\n';
  return code;
};
